package com.cheetah.support.redis;

import com.cheetah.config.Redis;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.Arrays;

/**
 * @Author Administrator
 * @Date 2019/9/19
 * @Version V1.0
 * @Description:
 **/
@Slf4j
public class RedisTemplateProcessor {

    public static final String REDIS = "REDIS";

    public static RedisTemplate getRedisTemplate(Redis redis) {
        RedisTemplate redisTemplate = null;

        switch (redis.getMode() == null ? "standalone" : redis.getMode()){
            case "standalone":
                redisTemplate = standaloneTemplate(redis);
                 log.info("init redis by standalone mode,config:{}",redis);
                return redisTemplate;
            case "sentinel":
                redisTemplate = sentinelTemplate(redis);
                log.info("init redis by sentinel mode,config:{}",redis);
                return redisTemplate;
            case "cluster":
                //TODO cluster模式待后续添加
                log.info("init redis by cluster mode,config:{}",redis);
                return redisTemplate;
            default:
                break;
        }
        return redisTemplate;
    }

    private static RedisTemplate standaloneTemplate(Redis v) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(v.getIp());
        redisStandaloneConfiguration.setPort(v.getPort());
        redisStandaloneConfiguration.setPassword(RedisPassword.of(v.getPassword()));
        redisStandaloneConfiguration.setDatabase(v.getDatabase());

        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration,getLettucePoolingClientConfiguration(v));
        factory.afterPropertiesSet();
        return getRedisTemplate(factory);
    }

    private static RedisTemplate sentinelTemplate(Redis v) {
        RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
        redisSentinelConfiguration.setDatabase(v.getDatabase());
        Arrays.stream(v.getNodes().split(",")).forEach(s -> {
            String[] nodes = StringUtils.split(s,":");
            redisSentinelConfiguration.addSentinel(new RedisNode(nodes[0],Integer.parseInt(nodes[1])));
        });

        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisSentinelConfiguration,getLettucePoolingClientConfiguration(v));
        factory.afterPropertiesSet();
        return getRedisTemplate(factory);
    }

    private static RedisTemplate<String, String> getRedisTemplate(LettuceConnectionFactory factory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);

        // 设置redis的String/Value的默认序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(stringRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    private static LettucePoolingClientConfiguration getLettucePoolingClientConfiguration(Redis v) {
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxTotal(v.getMaxTotal());
        config.setMaxWaitMillis(v.getMaxWait());
        config.setMaxIdle(v.getMaxIdle());
        config.setMinIdle(v.getMinIdle());
//        config.setTestOnCreate(v.getTestOnCreate());
//        config.setTestOnBorrow(v.getTestOnBorrow());
//        config.setTestOnReturn(v.getTestOnReturn());
//        config.setTestWhileIdle(v.getTestWhileIdle());
        return LettucePoolingClientConfiguration.builder()
                .poolConfig(config)
                .commandTimeout(Duration.ofMillis(5000))
                .shutdownTimeout(Duration.ofMillis(5000))
                .build();
    }
}
